feat: Add Enterprise Managed Authorization (SEP-990) support#1305
feat: Add Enterprise Managed Authorization (SEP-990) support#1305aniket-okta wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
|
|
||
| var tokens = await provider.GetAccessTokenAsync( | ||
| resourceUrl: new Uri("https://mcp-server.example.com"), | ||
| authorizationServerUrl: new Uri("https://auth.mcp-server.example.com")); |
There was a problem hiding this comment.
We experimented with adding some of these OAuth flows in #1178, but we haven't added it yet since it's an Auth Extension rather than a primary part of the spec. See https://github.com/modelcontextprotocol/ext-auth/blob/5c50488e96e242b4d09c2b97ae47fa152d96a836/specification/draft/enterprise-managed-authorization.mdx and https://github.com/modelcontextprotocol/conformance/blob/066b2d70800a8bd6bca82e000007c9877b443e5b/src/scenarios/client/auth/index.ts#L50-L55.
I do like that this doesn't pollute the ClientOAuthOptions like #1178 did, but I wonder if this wouldn't be better as a separate package. It looks like you could use these APIs to get the access token for any HttpClient needing to support these OAuth flows. It seems like something with more features like Duende.AccessTokenManagement.OpenIdConnect might be a better general solution for this than something tied specifically to the MCP C# SDK.
There was a problem hiding this comment.
Thanks for the review @halter73 ! Good points - I want to address the packaging question.
Why I placed this in ModelContextProtocol.Core:
- This was requested in Implement SEP-990: Enterprise Managed Authorization (Extension) #949, filed by the MCP spec team and tracked on the project board. Both the Go SDK (go-sdk#770) and TS SDK (typescript-sdk#1531) include this in their main packages - not as separate packages.
- While the underlying RFCs (8693, 7523) are generic, the implementation is MCP-specific - it uses the urn:ietf:params:oauth:token-type:id-jag token type, MCP resource URIs, and the EnterpriseAuthProvider is built around the MCP orchestrator context (ResourceUrl, AuthorizationServerUrl).
- Re: Duende - it handles OIDC token lifecycle for ASP.NET Core apps, but doesn't implement the ID-JAG token exchange or the MCP-specific JWT bearer grant pattern. Users would still need to orchestrate the full flow manually.
- There are conformance tests (CrossAppAccessCompleteFlowScenario) for this flow already.
That said, I'm happy to move this to a separate package (e.g. ModelContextProtocol.Auth.Enterprise) if the team prefers that pattern for auth extensions. The code is self-contained with no dependencies on SDK internals, so it would be a straightforward move. What do you think?
Implements Enterprise Managed Authorization (SEP-990) for the C# MCP SDK, enabling MCP Clients to leverage enterprise Identity Providers for seamless authorization without per-server user authentication.
Closes #949
Flow
Design
Layer 2:
EnterpriseAuthstatic class : standalone utilities (~680 lines)RequestJwtAuthorizationGrantAsync(): RFC 8693 token exchange (ID Token → ID-JAG)DiscoverAndRequestJwtAuthorizationGrantAsync(): convenience wrapper with IdP discoveryExchangeJwtBearerGrantAsync(): RFC 7523 JWT bearer grant (ID-JAG → Access Token)DiscoverAuthServerMetadataAsync(): OAuth authorization server metadata discoveryRequestJwtAuthGrantOptions,DiscoverAndRequestJwtAuthGrantOptions,ExchangeJwtBearerGrantOptionsJagTokenExchangeResponse,JwtBearerAccessTokenResponse,OAuthErrorResponseLayer 3:
EnterpriseAuthProvider: high-level provider with caching (~230 lines)InvalidateCache()EnterpriseAuthProviderOptionsfor configuration (ClientId, ClientSecret, Scope, AssertionCallback)Tests
36 unit tests covering both layers, passing on net8.0, net9.0, and net10.0.
Related